/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.fdm.tst.security;

import java.io.IOException;
import java.security.Principal;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

/**
 *
 * @author fdm
 */
public class AstjLoginModule implements LoginModule {
    
    private Subject subject;
    private CallbackHandler callbackHandler;
    private Map<String, ?> sharedState;
    private Map<String, ?> options;
    private Principal principal;

    @Override
    public void initialize (Subject         subject, 
                            CallbackHandler callbackHandler,
                            Map<String, ?>  sharedState, 
                            Map<String, ?>  options) {
        this.subject = subject;
        this.callbackHandler = callbackHandler;
        this.sharedState = sharedState;
        this.options = options;
    }

    @Override
    public boolean login() throws LoginException {
        if(callbackHandler == null){
            throw new LoginException("No CallbackHandler provided");
        }
        NameCallback nc = new NameCallback("Username");
        PasswordCallback pc = new PasswordCallback("Password", false);
        try {
            callbackHandler.handle(new Callback[] {nc, pc});
        } catch(IOException ex){
            throw new LoginException("Login interrupted by IOException");
        } catch(UnsupportedCallbackException ex){
            throw new LoginException("Login interrupted by UnsupportedCallbackException");
        }
        if(checkUsernamePassword(nc.getName(), pc.getPassword())){
            AstjUser user = new AstjUser();
            user.setId(nc.getName());
            user.setDisplayName(nc.getName());
            user.setEmail(nc.getName() + "@abc.com");
            principal = user;
            pc.clearPassword();
            return true;
        } else {
            pc.clearPassword();
            throw new LoginException("Login attempt failed");
        }
    }

    @Override
    public boolean commit() throws LoginException {
        if(principal != null){
            subject.getPrincipals().add(principal);
        }
        return true;
    }

    @Override
    public boolean abort() throws LoginException {
        this.principal = null;
        return true;
    }

    @Override
    public boolean logout() throws LoginException {
        this.subject.getPrincipals().clear();
        this.subject.getPrivateCredentials().clear();
        this.subject.getPublicCredentials().clear();
        return true;
    }

    private boolean checkUsernamePassword(String name, char[] password) {
        return  name != null && 
                password != null && 
                name.equalsIgnoreCase("admin") && 
                new String(password).equals("password"); // TODO: password gets leaked here?
    }
    
}
